% Autor:
% Fecha: 03/06/2013

:- dynamic posicion/2,orientacion/2,poseeLlave/1,accion/2,visitado/1,situacionActual/1,pared/2,llave/1,puerta/1,cerrojo/1,percepcion/6.

%%% Reglas diagnosticas

pared([X1,Y1],[X2,Y2]) :- percepcion([X1,Y1],pared,_,_,_,_),X2 is X1 - 1,Y2 is Y1.
pared([X1,Y1],[X2,Y2]) :- percepcion([X1,Y1],_,pared,_,_,_),X2 is X1,Y2 is Y1 + 1.
pared([X1,Y1],[X2,Y2]) :- percepcion([X1,Y1],_,_,pared,_,_),X2 is X1 + 1,Y2 is Y1.
pared([X1,Y1],[X2,Y2]) :- percepcion([X1,Y1],_,_,_,pared,_),X2 is X1,Y2 is Y1 - 1.
llave(Pos) :- percepcion(Pos,_,_,_,_,llave).
puerta(Pos) :- percepcion(Pos,_,_,_,_,salida).
cerrojo(Pos) :- percepcion(Pos,_,_,_,_,cerrojo).

%% pared([X1,Y1],[X2,Y2],S) :- percepcion([X1,Y1],0,_,_,_,_),situacionActual(S),X2 is X1 - 1,Y2 is Y1.
%% pared([X1,Y1],[X2,Y2],S) :- percepcion([X1,Y1],_,0,_,_,_),situacionActual(S),X2 is X1,Y2 is Y1 + 1.
%% pared([X1,Y1],[X2,Y2],S) :- percepcion([X1,Y1],_,_,0,_,_),situacionActual(S),X2 is X1 + 1,Y2 is Y1.
%% pared([X1,Y1],[X2,Y2],S) :- percepcion([X1,Y1],_,_,_,0,_),situacionActual(S),X2 is X1,Y2 is Y1 - 1.
%% llave(Pos,S) :- percepcion(Pos,_,_,_,_,1),situacionActual(S).
%% puerta(Pos,S) :- percepcion(Pos,_,_,_,_,2),situacionActual(S).
%% cerrojo(Pos,S) :- percepcion(Pos,_,_,_,_,3),situacionActual(S).

%%% Axiomas de estado sucesor

%% Acciones que cambian la posicion actual
est(S1) :- S1 > 0,S is S1-1,accion(avanzar,S),posicion(Pos1,S),adelante(Pos2,S),not(pared(Pos1,Pos2)),asserta(posicion(Pos2,S1)).

%% Acciones que NO cambian la posicion actual
est(S1) :- S1 > 0,S is S1-1,accion(girarIzq,S),posicion(Pos,S),asserta(posicion(Pos,S1)).
est(S1) :- S1 > 0,S is S1-1,accion(girarDer,S),posicion(Pos,S),asserta(posicion(Pos,S1)).
est(S1) :- S1 > 0,S is S1-1,accion(tomarLlave,S),posicion(Pos,S),asserta(posicion(Pos,S1)).

%% Acciones que cambian la orientacion actual
est(S1) :- S1 > 0,S is S1-1,accion(girarIzq,S),aLaIzquierda(O,S),asserta(orientacion(O,S1)).
est(S1) :- S1 > 0,S is S1-1,accion(girarDer,S),aLaDerecha(O,S),asserta(orientacion(O,S1)).

%% Acciones que NO cambian la orientacion actual
est(S1) :- S1 > 0,S is S1-1,accion(avanzar,S),orientacion(O,S),asserta(orientacion(O,S1)).
est(S1) :- S1 > 0,S is S1-1,accion(tomarLlave,S),orientacion(O,S),asserta(orientacion(O,S1)).

%% Otras
est(S1) :- S1 > 0,S is S1-1,accion(tomarLlave,S),hayLlave(S),asserta(poseeLlave(S1)).
est(S1) :- S1 > 0,S is S1-1,poseeLlave(S),asserta(poseeLlave(S1)).
est(S1) :- S1 > 0,S is S1-1,accion(avanzar,S),posicion(Pos,S),asserta(visitado(Pos)).

% est(S1) :- S1 > 0,S is S1-1,pared(Pos1,Pos2,S),asserta(pared(Pos1,Pos2,S1)).
% est(S1) :- S1 > 0,S is S1-1,llave(Pos,S),asserta(llave(Pos,S1)).
% est(S1) :- S1 > 0,S is S1-1,puerta(Pos,S),asserta(puerta(Pos,S1)).
% est(S1) :- S1 > 0,S is S1-1,cerrojo(Pos,S),asserta(cerrojo(Pos,S1)).

%%% Evaluacion de Acciones

excelente(noAction,S) :- posicion(Pos,S),puerta(Pos).
excelente(noAction,S) :- posicion(Pos,S),cerrojo(Pos),poseeLlave(S).
excelente(tomarLlave,S) :- hayLlave(S),not(poseeLlave(S)).

bueno(avanzar,S) :- posicion(Pos1,S),adelante(Pos2,S),not(pared(Pos1,Pos2)),not(visitado(Pos2)),accion(girarIzq,S1),S1 is S - 1.
bueno(girarIzq,S) :- posicion(Pos1,S),aLaIzquierda(O,S),alLado(Pos1,O,Pos2),not(pared(Pos1,Pos2)),not(visitado(Pos2)).
bueno(avanzar,S) :- posicion(Pos1,S),adelante(Pos2,S),not(pared(Pos1,Pos2)),not(visitado(Pos2)).
bueno(girarDer,S) :- posicion(Pos1,S),aLaDerecha(O,S),alLado(Pos1,O,Pos2),not(pared(Pos1,Pos2)),not(visitado(Pos2)).

regular(avanzar,S) :- posicion(Pos1,S),adelante(Pos2,S),not(pared(Pos1,Pos2)),accion(girarIzq,S1),S1 is S - 1.
regular(girarIzq,S) :- posicion(Pos1,S),aLaIzquierda(O,S),alLado(Pos1,O,Pos2),not(pared(Pos1,Pos2)).
regular(avanzar,S) :- posicion(Pos1,S),adelante(Pos2,S),not(pared(Pos1,Pos2)).
regular(girarDer,S) :- posicion(Pos1,S),aLaDerecha(O,S),alLado(Pos1,O,Pos2),not(pared(Pos1,Pos2)).
regular(girarIzq,_) :- true.

mejorAccion(X,S) :- excelente(X,S),!.
mejorAccion(X,S) :- bueno(X,S),!.
mejorAccion(X,S) :- regular(X,S),!.

%%% Sentencias Extras

adelante([X1,Y1],S) :- posicion([X2,Y2],S),orientacion([X3,Y3],S),X1 is X2 + X3,Y1 is Y2 + Y3.
alLado([X1,Y1],[X2,Y2],[X3,Y3]) :- X3 is X1 + X2,Y3 is Y1 + Y2.
aLaIzquierda([X1,Y1],S) :- orientacion([X2,Y2],S),X1 is Y2 * (-1),Y1 is X2.
aLaDerecha([X1,Y1],S) :- orientacion([X2,Y2],S),X1 is Y2,Y1 is X2 * (-1).
hayLlave(S) :- posicion(P,S),llave(P).
